#ifndef __MY_THREAD_POOL
#define __MY_THREAD_POOL
// 线程池的实现
#include<iostream>
#include<queue>
#include<pthread.h>
#include"Task.hpp"
    static const int thread_count=5;

pthread_t  threadId[thread_count];//用来管理线程id的数组
class ThreadPool
{
    private:
    std::queue<Task> task_queue;//任务队列 -> 一个交易场所
   static pthread_mutex_t lock_;//设置全局锁和条件变量不需要初始化和销毁
   static pthread_cond_t cond_;
   static pthread_mutex_t instan_lock;//获取单例使用的锁
   static ThreadPool*tp_;
   private:
   //设置成单例
       ThreadPool()=default;
        ThreadPool(const ThreadPool&)=delete;
        ThreadPool& operator=(const ThreadPool&)=delete;
    private:
    //对锁和条件变量的功能进行封装
    void Lock()
    {
        pthread_mutex_lock(&lock_);
    }
    void Unlock()
    {
        pthread_mutex_unlock(&lock_);
    }
    void Sleep()
    {
        pthread_cond_wait(&cond_,&lock_);
    }
    void WakeUp()
    {
        pthread_cond_signal(&cond_);
    }
    bool IsEmpty()
    {
        return task_queue.empty();
    }
    public:

    //任务处理
    static void* TaskProcessing(void* arg)
    {
        ThreadPool*tp=static_cast<ThreadPool*>(arg);
        while(true)
        {
        //1.获取任务 -> 从哪获取
      Task t;
      tp->Pop(t);
        //2. 执行任务
        t();
        }
        return nullptr;
    }

    //初始化线程池
    void InitPool()
    {
        //初始化线程池
        for(int i=0;i<thread_count;i++)
        {   
            pthread_create(&threadId[i],nullptr,TaskProcessing,this);
        }
    }

    //获取单例
   static ThreadPool*GetInstance()
    {
        if(tp_==nullptr)
        {
            pthread_mutex_lock(&instan_lock);
            if(tp_==nullptr)
            {
                tp_=new ThreadPool();
                tp_->InitPool();
            }
            pthread_mutex_unlock(&instan_lock);

        }
        return tp_;
    }
    //添加任务
    void Push(const Task&t)
    {
        Lock();
        task_queue.push(t);
        WakeUp();
        Unlock();
    }
    //获取任务
    void Pop(Task&t)
    {
        //避免多线程并发访问产生的数据不一致的问题,用锁来解决
        Lock();
        while(IsEmpty())
        {
            Sleep();
        }
        t=task_queue.front();
        task_queue.pop();
        Unlock();
    }
     ~ThreadPool()
    {
        //等待线程
        for(int i=0;i<thread_count;i++)
        {
        pthread_join(threadId[i],nullptr);

        }
    }

};
ThreadPool* ThreadPool::tp_=nullptr;
pthread_cond_t ThreadPool::cond_=PTHREAD_COND_INITIALIZER;
pthread_mutex_t ThreadPool::lock_=PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t ThreadPool::instan_lock=PTHREAD_MUTEX_INITIALIZER;

#endif
